﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Xml;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Taxonomy;

namespace MetadataMigrator
{
    public partial class MetadataMigrator : Form
    {
        public TaxonomySession session;
        public TermStore selected_termstore;
        public Group selected_group;
        public TermSet selected_termset;
        public XmlDocument exported;
        public XmlDocument imported;
        public TermSet newtermset;
        public Working working;
        public UpdateMMFields updatemmfields;

        public MetadataMigrator()
        {
            InitializeComponent();
        }

        private void MetadataMigrator_Load(object sender, EventArgs e)
        {
            working = new Working();
            working.StartPosition = FormStartPosition.CenterParent;
            updatemmfields = new UpdateMMFields();
            this.ActiveControl = txtSiteURL;

            toolTip1.SetToolTip(txtSiteURL, "Enter any site collection URL from the farm");
            toolTip2.SetToolTip(lstTermStores, "List of term stores in the farm");
            toolTip3.SetToolTip(lstGroups, "List of groups in the selected term stores");
            toolTip4.SetToolTip(lstTermSets, "List of term sets in the selected group");
            toolTip5.SetToolTip(btnImportTermSet, "Import a term set into the selected group");
            toolTip6.SetToolTip(btnExportTermSet, "Export the selected term set");
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (txtSiteURL.Text == "")
            {
                MessageBox.Show("Please enter a site collection URL");
            }
            else
            {
                working.Show();
                working.Refresh();
                lstTermStores.Items.Clear();
                Cursor.Current = Cursors.WaitCursor;
                using (SPSite site = new SPSite(txtSiteURL.Text))
                {
                    session = new TaxonomySession(site);
                    foreach (TermStore termstore in session.TermStores)
                    {
                        lstTermStores.Items.Add(termstore.Name);
                    }
                }
                Cursor.Current = Cursors.Default;
                working.Hide();
            }
        }

        private void lstTermStores_SelectedIndexChanged(object sender, EventArgs e)
        {
            selected_termstore = session.TermStores[lstTermStores.SelectedItem.ToString()];
            RefreshGroups();
        }

        private void lstGroups_SelectedIndexChanged(object sender, EventArgs e)
        {
            selected_group = selected_termstore.Groups[lstGroups.SelectedItem.ToString()];
            RefreshTermSets();
        }

        private void lstTermSets_SelectedIndexChanged(object sender, EventArgs e)
        {
            selected_termset = selected_group.TermSets[lstTermSets.SelectedItem.ToString()];
        }

        private void btnExportTermSet_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if (lstTermSets.SelectedItem == null)
            {
                Cursor.Current = Cursors.Default;
                MessageBox.Show("Please select a term set to export");
            }
            else
            {
                selected_termset = selected_group.TermSets[lstTermSets.SelectedItem.ToString()];
                exported = new XmlDocument();
                XmlDeclaration dec = exported.CreateXmlDeclaration("1.0", null, null);
                exported.AppendChild(dec);
                ExportTermSet(selected_termset);
                Cursor.Current = Cursors.Default;

                saveFileDialog.Filter = "XML files (*.xml)|*.xml";
                saveFileDialog.FilterIndex = 0;
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    exported.Save(saveFileDialog.FileName);
                    MessageBox.Show("Export successful", "Export successful", MessageBoxButtons.OK);
                }
            }
        }

        private void ExportTermSet(TermSet selected_termset)
        {
            //term store and group info for the selected term set
            TermStore termstore = selected_termset.TermStore;
            XmlElement termstorenode = exported.CreateElement("TermStore");
            termstorenode.SetAttribute("Id", termstore.Id.ToString());
            termstorenode.SetAttribute("Name", termstore.Name);
            exported.AppendChild(termstorenode);
            Group group = selected_termset.Group;
            XmlElement groupnode = exported.CreateElement("Group");
            groupnode.SetAttribute("Id", group.Id.ToString());
            groupnode.SetAttribute("Name", group.Name);
            groupnode.SetAttribute("Description", group.Description);
            SPAcl<TaxonomyRights> managers = group.GroupManagers;
            XmlElement groupmanagersnode = exported.CreateElement("GroupManagers");
            groupnode.AppendChild(groupmanagersnode);
            foreach (SPAce<TaxonomyRights> manager in managers)
            {
                string[] groupmanager_parts = manager.PrincipalName.Split('|');
                XmlElement groupmanagernode = exported.CreateElement("GroupManager");
                groupmanagernode.SetAttribute("Name", groupmanager_parts[1]);
                groupmanagersnode.AppendChild(groupmanagernode);
            }
            SPAcl<TaxonomyRights> contributors = group.Contributors;
            XmlElement contributorsnode = exported.CreateElement("Contributors");
            groupnode.AppendChild(contributorsnode);
            foreach (SPAce<TaxonomyRights> contributor in contributors)
            {
                string[] contributor_parts = contributor.PrincipalName.Split('|');
                XmlElement contributornode = exported.CreateElement("Contributor");
                contributornode.SetAttribute("Name", contributor_parts[1]);
                contributorsnode.AppendChild(contributornode);
            }
            termstorenode.AppendChild(groupnode);            

            //term set node
            XmlElement termsetnode = exported.CreateElement("TermSet");
            termsetnode.SetAttribute("Id", selected_termset.Id.ToString());
            termsetnode.SetAttribute("Name", selected_termset.Name);
            termsetnode.SetAttribute("Description", selected_termset.Description);
            termsetnode.SetAttribute("Owner", selected_termset.Owner);
            termsetnode.SetAttribute("Contact", selected_termset.Contact);

            XmlElement stakeholdersnode = exported.CreateElement("Stakeholders");
            termsetnode.AppendChild(stakeholdersnode);
            foreach (string stakeholder in selected_termset.Stakeholders)
            {
                string[] stakeholder_parts = stakeholder.Split('|');
                XmlElement stakeholdernode = exported.CreateElement("Stakeholder");
                stakeholdernode.SetAttribute("Login", stakeholder_parts[1]);
                stakeholdersnode.AppendChild(stakeholdernode);
            }

            termsetnode.SetAttribute("IsOpenForTermCreation", selected_termset.IsOpenForTermCreation.ToString());
            termsetnode.SetAttribute("IsAvailableForTagging", selected_termset.IsAvailableForTagging.ToString());
            groupnode.AppendChild(termsetnode);

            if (selected_termset.Terms.Count > 0)
            {
                XmlElement termsnode = exported.CreateElement("Terms");
                termsetnode.AppendChild(termsnode);
                foreach (Term term in selected_termset.Terms)
                {
                    ExportTerm(termsnode, term);
                }
            }
        }

        private void ExportTerm(XmlElement parentnode, Term term)
        {
            //term node
            XmlElement termnode = exported.CreateElement("Term");
            termnode.SetAttribute("Id", term.Id.ToString());
            termnode.SetAttribute("Name", term.Name);
            termnode.SetAttribute("IsAvailableForTagging", term.IsAvailableForTagging.ToString());
            termnode.SetAttribute("IsKeyword", term.IsKeyword.ToString());
            termnode.SetAttribute("IsRoot", term.IsRoot.ToString());

            XmlElement labelsnode = exported.CreateElement("Labels");
            termnode.AppendChild(labelsnode);

            foreach (Microsoft.SharePoint.Taxonomy.Label label in term.Labels)
            {
                XmlElement labelnode = exported.CreateElement("Label");
                labelnode.SetAttribute("IsDefaultForLanguage", label.IsDefaultForLanguage.ToString());
                labelnode.SetAttribute("Language", label.Language.ToString());
                labelnode.SetAttribute("Value", label.Value);
                labelsnode.AppendChild(labelnode);
            }

            parentnode.AppendChild(termnode);

            if (term.Terms.Count > 0)
            {
                XmlElement childtermsnode = exported.CreateElement("Terms");
                termnode.AppendChild(childtermsnode);
                foreach (Term childterm in term.Terms)
                {
                    ExportTerm(childtermsnode, childterm);
                }
            }
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if (lstGroups.SelectedItem == null)
            {
                Cursor.Current = Cursors.Default;
                MessageBox.Show("Please select a group to import the term set");
            }
            else
            {
                openFileDialog.Filter = "XML files (*.xml)|*.xml";
                openFileDialog.FilterIndex = 0;
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string file = openFileDialog.FileName;
                    try
                    {
                        imported = new XmlDocument();
                        imported.Load(file);

                        working.Show();
                        working.Refresh();

                        ImportTermSet();

                        working.Hide();

                        TermSet check_import = null;
                        try
                        {
                            check_import = selected_group.TermSets[newtermset.Name];
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            MessageBox.Show("Import failed");
                        }

                        if (check_import != null)
                        {
                            MessageBox.Show("Import successful", "Import successful", MessageBoxButtons.OK);
                            lstTermSets.Items.Add(newtermset.Name);
                            RefreshTermSets();
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Oops!\n" + ex.Message);
                    }
                }

                Cursor.Current = Cursors.Default;
            }
        }

        private void ImportTermSet()
        {
            XmlNodeList termsetnodes = imported.SelectNodes("/TermStore/Group/TermSet");
            foreach (XmlNode termsetnode in termsetnodes)
            {
                newtermset = selected_group.CreateTermSet(termsetnode.Attributes["Name"].Value, new Guid(termsetnode.Attributes["Id"].Value));
                newtermset.Description = termsetnode.Attributes["Description"].Value;
                try
                {
                    newtermset.Owner = termsetnode.Attributes["Owner"].Value;
                }
                catch (ArgumentException)
                {
                    newtermset.Owner = "";
                }
                newtermset.Contact = termsetnode.Attributes["Contact"].Value;
                newtermset.IsOpenForTermCreation = Convert.ToBoolean(termsetnode.Attributes["IsOpenForTermCreation"].Value);
                newtermset.IsAvailableForTagging = Convert.ToBoolean(termsetnode.Attributes["IsAvailableForTagging"].Value);

                selected_termstore.CommitAll();

                XmlNodeList termnodes = termsetnode.SelectNodes("./Terms/Term");
                foreach (XmlNode termnode in termnodes)
                {
                    Term newterm = newtermset.CreateTerm(termnode.Attributes["Name"].Value, 1033, new Guid(termnode.Attributes["Id"].Value));
                    newterm.IsAvailableForTagging = Convert.ToBoolean(termnode.Attributes["IsAvailableForTagging"].Value);
                    XmlNodeList labelnodes = termnode.SelectNodes("./Labels/Label");
                    foreach (XmlNode labelnode in labelnodes)
                    {
                        if ((labelnode.Attributes["Language"].Value == "1033") && (labelnode.Attributes["IsDefaultForLanguage"].Value == "False"))
                        {
                            newterm.CreateLabel(labelnode.Attributes["Value"].Value, 1033, false);
                        }
                        if (labelnode.Attributes["Language"].Value == "1036")
                        {
                            newterm.CreateLabel(labelnode.Attributes["Value"].Value, 1036, Convert.ToBoolean(labelnode.Attributes["IsDefaultForLanguage"].Value));
                        }
                    }
                    selected_termstore.CommitAll();

                    XmlNodeList childtermnodes = termnode.SelectNodes("./Terms/Term");
                    foreach (XmlNode childtermnode in childtermnodes)
                    {
                        ImportTerm(newterm, childtermnode);
                    }
                }
            }
        }

        private void ImportTerm(Term parenttermnode, XmlNode childtermnode)
        {
            Term newterm = parenttermnode.CreateTerm(childtermnode.Attributes["Name"].Value, 1033, new Guid(childtermnode.Attributes["Id"].Value));
            newterm.IsAvailableForTagging = Convert.ToBoolean(childtermnode.Attributes["IsAvailableForTagging"].Value);
            XmlNodeList labelnodes = childtermnode.SelectNodes("./Labels/Label");
            foreach (XmlNode labelnode in labelnodes)
            {
                if ((labelnode.Attributes["Language"].Value == "1033") && (labelnode.Attributes["IsDefaultForLanguage"].Value == "False"))
                {
                    newterm.CreateLabel(labelnode.Attributes["Value"].Value, 1033, false);
                }
                if (labelnode.Attributes["Language"].Value == "1036")
                {
                    newterm.CreateLabel(labelnode.Attributes["Value"].Value, 1036, Convert.ToBoolean(labelnode.Attributes["IsDefaultForLanguage"].Value));
                }
            }
            selected_termstore.CommitAll();

            XmlNodeList childtermnodes = childtermnode.SelectNodes("./Terms/Term");
            foreach (XmlNode grandchildtermnode in childtermnodes)
            {
                ImportTerm(newterm, grandchildtermnode);
            }
        }

        private void btnDeleteGroup_Click(object sender, EventArgs e)
        {
            try
            {
                selected_group.Delete();
                selected_termstore.CommitAll();
                lstGroups.Items.Remove(selected_group);
                RefreshGroups();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

        private void btnDeleteTermSet_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Are you sure you want to delete this group?");
            if (DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    selected_termset.Delete();
                    selected_termstore.CommitAll();
                    lstTermSets.Items.Remove(selected_termset);
                    RefreshTermSets();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void btnUpdateMMField_Click(object sender, EventArgs e)
        {
            updatemmfields.StartPosition = FormStartPosition.CenterParent;
            updatemmfields.Show();
        }

        private void RefreshGroups()
        {
            lstGroups.Items.Clear();
            lstTermSets.Items.Clear();
            foreach (Group group in selected_termstore.Groups)
            {
                lstGroups.Items.Add(group.Name);
            }
        }

        private void RefreshTermSets()
        {
            lstTermSets.Items.Clear();
            foreach (TermSet termset in selected_group.TermSets)
            {
                lstTermSets.Items.Add(termset.Name);
            }
        }


    }
}
